package com.rankeiot.platform.service;

import cn.hutool.core.img.ImgUtil;
import com.rankeiot.core.data.response.Resp;
import com.rankeiot.core.util.IDUtil;
import com.rankeiot.core.util.StringUtil;
import lombok.SneakyThrows;
import org.sagacity.sqltoy.utils.DateUtil;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class LocalFileStoreService implements IFileStoreService {
    private String localPath;
    private static Random rnd = new Random();

    public LocalFileStoreService(String localPath) {
        //StaticMappings.add("/"+localPath+"/", new FileStaticRepository(localPath));
        this.localPath = localPath;
    }

    private static String randomName() {
        return IDUtil.toString(Math.abs(rnd.nextLong())).toUpperCase();
    }

    private static synchronized String createRandomFile(String basePath, String extension) throws IOException {
        String filePath = basePath + randomName() + extension;
        File dist = new File(filePath);
        //避免文件名重复
        while (dist.exists()) {
            filePath = basePath + randomName() + extension;
            dist = new File(filePath);
        }
        dist.createNewFile();
        return filePath;
    }

    @Override
    public Resp<String> save(InputStream file, String fileName, String user) throws IOException {
        Date now = new Date();
        String subPath = DateUtil.formatDate(now, "YYYY/MMdd") + "/" + user;
        File dir = new File(localPath, subPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        String extension = fileName;
        int idx = extension.lastIndexOf('.');
        if (idx > 0) {
            extension = extension.substring(idx);
        } else {
            extension = ".unknown";
        }
        String filePath = createRandomFile(localPath + "/" + subPath + "/", extension);
        FileCopyUtils.copy(file, new FileOutputStream(filePath));
        return Resp.of(filePath);
    }

    @Override
    public Resp delete(String path, String user) {
        if (StringUtil.isEmpty(path)) {
            Resp.fail("文件名不能为空");
        }
        if (!path.startsWith(localPath + "/") || path.indexOf("..") > -1) {
            Resp.fail("文件删除错误");
        }
        if (user != null) {
            if (path.indexOf("/" + user + "/") == -1) {
                Resp.fail("无权限");
            }
        }
        File dist = new File(path);
        if (dist.exists()) {
            dist.delete();
        }
        return Resp.ok();
    }


    @Override
    public ResponseEntity getFile(String path, String query) {
        File file = new File(".", path);
        File realFile=file;
        if (!file.exists()) {
            return ResponseEntity.notFound().build();
        }


        if (query != null) {
            if ("image".equals(MediaTypeFactory.getMediaType(file.getName()).get().getType())) {
                //small
                if ("small".equals(query)) {
                   String newPath = path.replaceFirst("(\\.\\w+)$","_small$1");
                   realFile = new File(".", newPath);
                    if (realFile.exists()) {

                    } else {
                        //small 300*200
                        BufferedImage image = ImgUtil.read(file);
                        int w=image.getWidth();
                        int h=image.getHeight();
                        //目标宽度
                        int rW=300;
                        //目标高度
                        int rH=200;

                        float f=rW*1.0f/rH;
                        float scale=1.0f;
                        //判断高宽比例
                        if(w*1.0/h < f){
                            //以高度为准
                            if(h<rH){
                              ImgUtil.write(image,realFile);
                            }else{
                                ImgUtil.scale(image,realFile,rH*1.0f/h);
                            }
                        }else{
                            //以宽度为准
                            if(w<rW){
                                ImgUtil.write(image,realFile);
                            }else{
                                ImgUtil.scale(image,realFile,rW*1.0f/w);
                            }
                        }
                    }
                }
            }
        }

        ResponseEntity entity = ResponseEntity.ok()
                .lastModified(realFile.lastModified())
                .contentType(MediaTypeFactory.getMediaType(file.getName()).orElse(MediaType.APPLICATION_OCTET_STREAM))
                .header("Content-Disposition", "inline;filename=" + file.getName())
                .contentLength(realFile.length())
                .cacheControl(CacheControl.maxAge(5, TimeUnit.MINUTES).cachePublic())
                .body(new FileSystemResource(realFile));
        return entity;
    }



    @Override
    public List<FileInfo> list(String path) {
        File file = new File(".", path);
        if (!file.exists()) {
            return new ArrayList<>();
        }
        List result = new ArrayList();
        for (File f : file.listFiles()) {
            String name = f.getName();
            String type = "unknown";
            if (f.isDirectory()) {
                type = "dir";
            } else if (name.indexOf(".") > -1) {
                type = name.substring(name.lastIndexOf(".") + 1).toLowerCase();
            }
            FileInfo fi = new FileInfo(name, f.length(), f.lastModified(), type);
            result.add(fi);
        }
        return result;
    }

}
